﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

#endregion

namespace ScrumTable.Common.Collections
{
    /// <summary>
    /// Defines a Name/Value object for named values.
    /// </summary>
    public class NamedValue<T>
        where T : class
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------
        
        private string _name;

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------

        /// <summary>
        /// Gets a label/name for the value.
        /// </summary>
        public string Name
        {
            get { return _name ?? Value.ToString(); }
            private set { _name = value; }
        }

        /// <summary>
        /// Specifies the value reference.
        /// </summary>
        public T Value { get; private set; }

        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        ///<summary>
        /// Create a NamedValue
        ///</summary>
        /// <param name="name">The key from the system</param>
        /// <param name="value">value of the report parameter </param>
        public NamedValue(string name, T value)
        {
            PreCondition.AssertNotNull(value, "value");

            Name = name;
            Value = value;
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// Determines whether the specified NamedValue is equal to the current instance.
        /// </summary>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <param name="other">The NamedValue to compare with the current instance. </param>
        public bool Equals(NamedValue<T> other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.Value, Value);
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. 
        ///                 </param><exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.
        ///                 </exception><filterpriority>2</filterpriority>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof(NamedValue<T>)) return false;
            return Equals((NamedValue<T>)obj);
        }

        /// <summary>
        /// Serves as a hash function for a particular type. 
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        /// <filterpriority>2</filterpriority>
        public override int GetHashCode()
        {
            return Value.GetHashCode();
        }

        /// <summary>
        /// Override == operator in order to check objects equality.
        /// </summary>
        /// <param name="left">The NamedValue to compare with the right instance. </param>
        /// <param name="right">The NamedValue to compare with the left instance. </param>
        /// <returns>Returns true if the objects are the same.</returns>
        public static bool operator ==(NamedValue<T> left, NamedValue<T> right)
        {
            return Equals(left, right);
        }

        /// <summary>
        /// Override != operator in order to check objects equality.
        /// </summary>
        /// <param name="left">The NamedValue to compare with the right instance. </param>
        /// <param name="right">The NamedValue to compare with the left instance. </param>
        /// <returns>Returns true if the objects aren't the same.</returns>
        public static bool operator !=(NamedValue<T> left, NamedValue<T> right)
        {
            return !Equals(left, right);
        }

        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        #endregion
    }


    /// <summary>
    /// Defines a Name/Value object for named values.
    /// </summary>
    public class NamedValue : NamedValue<string>
    {
        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        ///<summary>
        /// Create a NamedValue.
        ///</summary>
        /// <param name="name">The key from the system</param>
        /// <param name="value">value of the report parameter </param>
        public NamedValue(string name, string value)
            : base(name, value)
        {
        }

        #endregion
    }
}